#include "Updater.h"


#include "_Global/Platform/Platform.h"


#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>



Updater::Updater(QObject *parent)
    : QObject(parent)
{
    /*
    //应用程序在屏幕中间：
    QDesktopWidget *deskdop = QApplication::desktop();
    this->move((deskdop->width() -this->width())/2, (deskdop->height() - this->height())/2);

    //无标题栏：
    this->setWindowFlags(Qt::FramelessWindowHint);//没有标题栏

    //隐藏菜单栏和工具栏
    this->ui->menuBar->hide();
    this->ui->mainToolBar->hide();

    //固定高和宽：

    this->setFixedSize(400,200);

    //设置背景颜色（两种方法都可以）
    //this->setStyleSheet("QMainWindow{background:rgb(240,250,250)}");
    QPalette pal;
    pal.setColor(QPalette::Background,QColor(255,245,225) );
    this->setPalette(pal);
    this->setAutoFillBackground(true);
*/

    m_nNewVersion = -1;
    m_nOldVersion = -1;
    m_nToTalFileCount = 0;
    m_nUpdatedFileCount = 0;



    connect(&m_HTTPDownload, SIGNAL(s_finished(int, QNetworkReply::NetworkError, int)),
            this, SLOT(onJsonDownloadFinished(int, QNetworkReply::NetworkError, int)));

}

Updater::~Updater()
{

}

bool Updater::startUpdate(QUrl urlUpdateInfoJson)
{
    //下载UpdateInfo.json文件到内存
    if(m_HTTPDownload.download(urlUpdateInfoJson, "", false) < 0)
    {
        qCritical() << _T("[!Updater]Download Json ERROR!");
        emit s_UpdateFinished(-1, _T("升级失败，请检查网络和升级配置！"));
        return false;
    }
    return true;
}

void Updater::UpdateSuccessed(bool bUpdated)
{
    emit s_UpdateProccess(m_nToTalFileCount, m_nToTalFileCount);

    if(bUpdated)
    {
        deleteOldFiles();

        emit s_UpdateMessage("升级完毕");

        //把最新的UpdateInfo.json写入
        QFile fileJsonUpdateInfo(FIXLOCALPATH_W("UpdateInfo.json"));
        if(!fileJsonUpdateInfo.open(QIODevice::WriteOnly))
        {
            qCritical() << "[!Updater]UpdateInfo.json Write ERROR!";
            emit s_UpdateFinished(-1, "UpdateInfo.json写入失败，请重试！");
            return;
        }
        else
        {
            //!!!这里应该改为:完全升级成功后,再进行保存json
            fileJsonUpdateInfo.write(m_baNewJsonData);
            fileJsonUpdateInfo.flush();
            fileJsonUpdateInfo.close();
        }
        emit s_UpdateFinished(1, "");
    }
    else
    {
        s_UpdateMessage("已经是最新版本");
        emit s_UpdateFinished(0, "");
    }

}

void Updater::onJsonDownloadFinished(int errorType, QNetworkReply::NetworkError error, int status_code)
{
    //返回 没问题,且 状态码为200
    if(0 == errorType && QNetworkReply::NoError == error && 200 == status_code)
    {
        m_baNewJsonData = m_HTTPDownload.m_baHttpData;
        qDebug() << "---------------";
        qDebug() << m_baNewJsonData;
        qDebug() << "---------------";


//读取网络的新Json文件 并 解析出 所有新配置
        if(!parseJsonVersion(m_HTTPDownload.m_baHttpData, m_nNewVersion, m_mapNewFileInfo, m_strBaseDownloadUrl))
        {
            qCritical() << "[!Updater]Parse Json New Version ERROR!";
            emit s_UpdateFinished(-1, "升级文件Json解析失败,请检查网络连接或升级地址！");
            return;
        }


//读取本地Json文件 并 解析出 所有旧配置
        QFile fileJsonUpdateInfo(FIXLOCALPATH_W("UpdateInfo.json"));
        if(!fileJsonUpdateInfo.open(QIODevice::ReadOnly))
        {
            qCritical() << "[!Updater]NO Json File ERROR!";
            emit s_UpdateFinished(-1, "缺少配置文件：UpdateInfo.json！");
            return;
            //m_nOldVersion = 0;
            //return;
        }
        QByteArray baJsonUpdateInfo = fileJsonUpdateInfo.readAll();
        fileJsonUpdateInfo.close();

        QString tmpBaseURL;
        if(!parseJsonVersion(baJsonUpdateInfo, m_nOldVersion, m_mapOldFileInfo, tmpBaseURL))
        {
            qCritical()<<"[!Updater]Json Parse Old Version ERROR!";
            emit s_UpdateFinished(-1, "UpdateInfo.json解析失败！");
            return;
            //m_nOldVersion = 0;
        }



//开始升级
        m_nToTalFileCount = m_mapNewFileInfo.count();
        emit s_UpdateProccess(0, m_nToTalFileCount);

        //判断新旧总版本号
        if(m_nNewVersion == m_nOldVersion)
        {
            UpdateSuccessed(false);
            return;
        }
        else if(m_nNewVersion < m_nOldVersion)
        {
            qCritical()<<"[!Updater]Version ERROR:"<< m_nNewVersion << m_nOldVersion;
            emit s_UpdateFinished(-1, "版本错误!");
            return;
        }
        else    //升级操作
        {
            emit s_UpdateMessage("正在升级，请稍候...");

            //重新连接下载成功信号（到文件下载完成函数）
            disconnect(&m_HTTPDownload, SIGNAL(s_finished(int QNetworkReply::NetworkError, int)), this, SLOT(onJsonDownloadFinished(int, QNetworkReply::NetworkError, int)));
            connect(&m_HTTPDownload, SIGNAL(s_finished(int QNetworkReply::NetworkError, int)), this, SLOT(onFileDownloadFinished(int, QNetworkReply::NetworkError, int)));

            //开始循环升级
            m_mapInteratorFileInfo = m_mapNewFileInfo.constBegin();
            updateFiles();

        }
    }
    else
    {
        qCritical() << "[!Updater]JsonDownload ERROR:" << errorType << error << status_code;
        emit s_UpdateFinished(-1, "获取Json升级文件信息失败,请检查!");
    }
}

void Updater::onFileDownloadFinished(int errorType, QNetworkReply::NetworkError error, int status_code)
{
    if(0 == errorType && QNetworkReply::NoError == error && 200 == status_code)
    {
        if(m_UpdateFileInfo.m_nOldFileVersion == -1)
            emit s_OperateFileInfo(m_UpdateFileInfo.m_strNewFilePath, _Operate_Create, _Operate_Success);
        else
            emit s_OperateFileInfo(m_UpdateFileInfo.m_strNewFilePath, _Operate_Replace, _Operate_Success);

        //继续下载下一个
        updateFiles();
    }
    else
    {
        if(m_UpdateFileInfo.m_nOldFileVersion == -1)
            emit s_OperateFileInfo(m_UpdateFileInfo.m_strNewFilePath, _Operate_Create, _Operate_Fail, status_code);
        else
            emit s_OperateFileInfo(m_UpdateFileInfo.m_strNewFilePath, _Operate_Replace, _Operate_Fail, status_code);

        qCritical() << "[!Updater]FileDownload ERROR:" << errorType << error << status_code;
        emit s_UpdateFinished(-1, "升级文件失败,请检查网络连接或其他原因!");
    }
}

void Updater::updateFiles()
{
    while(1)
    {
        if(m_mapInteratorFileInfo == m_mapNewFileInfo.constEnd())   //升级到最后一个文件,则结束
        {
            UpdateSuccessed(true);

            return;
        }

        emit s_UpdateProccess(m_nUpdatedFileCount++, m_nToTalFileCount);

        //从新FileInfo.Json的文件信息Map中取出一个新文件,获取其 路径 和 版本
        m_UpdateFileInfo.m_strNewFilePath = m_mapInteratorFileInfo.key();
        m_UpdateFileInfo.m_nNewFileVersion = m_mapInteratorFileInfo.value().toMap().value("Version").toInt();

        //解析出旧FileInfo.json文件版本
        if(m_mapOldFileInfo.contains(m_UpdateFileInfo.m_strNewFilePath))    //如果旧文件中有 新文件路径
            m_UpdateFileInfo.m_nOldFileVersion = m_mapOldFileInfo.value(m_UpdateFileInfo.m_strNewFilePath).toMap().value("Version").toInt();
        else
            m_UpdateFileInfo.m_nOldFileVersion = -1;

        if(m_UpdateFileInfo.m_nNewFileVersion < m_UpdateFileInfo.m_nOldFileVersion)    //版本有问题
            emit s_UpdateMessage(_T("%1 文件版本号有问题：%2，%3")
                                 .arg(m_UpdateFileInfo.m_strNewFilePath)
                                 .arg(m_UpdateFileInfo.m_nNewFileVersion)
                                 .arg(m_UpdateFileInfo.m_nOldFileVersion)
                                 );
        if(m_UpdateFileInfo.m_nNewFileVersion == m_UpdateFileInfo.m_nOldFileVersion)    //如果不需要升级
        {
            emit s_OperateFileInfo(m_UpdateFileInfo.m_strNewFilePath, _Operate_Nothing, _Operate_Success);
            m_mapInteratorFileInfo ++;

            continue;
        }
        else
        {
            qDebug() << "Updating:" << m_strBaseDownloadUrl << m_UpdateFileInfo.m_strNewFilePath;
            emit s_UpdateMessage(_T("正在下载：%1").arg(m_strBaseDownloadUrl + m_UpdateFileInfo.m_strNewFilePath));

            //下载
            if(m_HTTPDownload.download(QUrl(m_strBaseDownloadUrl + m_UpdateFileInfo.m_strNewFilePath), m_UpdateFileInfo.m_strNewFilePath) < 0)
            {
                qCritical() << _T("[!Updater]Download ERROR!");
                emit s_UpdateFinished(-1, _T("升级失败，请检查网络和升级配置！"));
                return;
            }

            m_mapInteratorFileInfo ++;

            return;
        }
    }
}

void Updater::deleteOldFiles()
{
    QVariantMap::const_iterator fileMapInterator;   //遍历所有旧文件信息中的 某个新文件
    for(fileMapInterator = m_mapOldFileInfo.constBegin(); fileMapInterator != m_mapOldFileInfo.constEnd(); fileMapInterator++)
    {
        //从旧文件Json信息的Map中取出一个旧文件,获取其 路径 和 版本
        QString oldFilePath = fileMapInterator.key();


        //int oldVersion = fileMapInterator.value().toMap().value("Version").toInt();
        //int newVersion;
        //if(m_mapNewFileInfo.contains(oldFilePath))    //如果新文件中有
        //    newVersion = m_mapNewFileInfo.value(oldFilePath).toMap().value("Version").toInt();

        //解析出新文件版本
        if(!m_mapNewFileInfo.contains(oldFilePath))    //如果新文件中没有
        {
            qDebug() << "[Updater]Deleting:" << m_strBaseDownloadUrl << oldFilePath;
            if(QFile::exists(oldFilePath)) //如果文件已经存在，那么删除
            {
                if(QFile::remove(oldFilePath))
                    emit s_OperateFileInfo(oldFilePath, _Operate_Delete, _Operate_Success);
                else
                    emit s_OperateFileInfo(oldFilePath, _Operate_Delete, _Operate_Fail);
            }
        }
    }
}

bool Updater::parseJsonVersion(QByteArray &baJsonData, int &version, QVariantMap &mapFileInfo, QString &baseURL)
{
    QJsonParseError jsonError;
    QJsonDocument document = QJsonDocument::fromJson(baJsonData, &jsonError);  //转化为 JSON 文档
    if (!document.isNull() && (jsonError.error == QJsonParseError::NoError))  //解析未发生错误
    {
        if (document.isObject()) //JSON 文档为对象
        {
            QJsonObject rootObject = document.object();  //转化为对象

            //总Version
            if (rootObject.contains("Version"))   // 包含指定的 key
            {
                QJsonValue value = rootObject.value("Version");  //获取指定 key 对应的 value
                if (value.isString())  //判断 value 是否为字符串
                {
                    //QString strName = value.toString();  //将 value 转化为字符串
                    version = value.toString().toInt();
                }
                else if (value.isDouble())  //判断 value 是否为
                {
                    //qDebug() << "Version : " << value.toDouble();
                    version = value.toInt();
                }
                else
                {
                    qCritical() << "[!Updater]Version ERROR!";
                    return false;
                }
            }
            else
            {
                qCritical() << "[!Updater]NO Version ERROR!";
                return false;
            }

            //BaseURL
            if (rootObject.contains("BaseURL"))
            {
                QJsonValue value = rootObject.value("BaseURL");
                baseURL = value.toString();
                qDebug() << "baseURL:" << baseURL;
                //qDebug()<<value.toArray().toVariantList();
            }
            else
            {
                qCritical()<<"[!Updater]NO BaseURL ERROR!";
                return false;
            }

            //FileList
            if (rootObject.contains("FileList"))
            {
                QJsonValue value = rootObject.value("FileList");
                mapFileInfo = value.toObject().toVariantMap();
                //qDebug()<<value.toArray().toVariantList();
            }
            else
            {
                qCritical()<<"[!Updater]NO FileList ERROR!";
                return false;
            }
        }
        else
        {
            qCritical()<<"[!Updater]Json Root ERROR!";
            return false;
        }
    }
    else
    {
        qCritical()<<"[!Updater]Json ERROR!";
        return false;
    }

    return true;
}












bool Updater::parseJsonFiles(QByteArray &baJsonData)
{
    QJsonParseError jsonError;
    QJsonDocument document = QJsonDocument::fromJson(baJsonData, &jsonError);  // 转化为 JSON 文档
    if (!document.isNull() && (jsonError.error == QJsonParseError::NoError)) {  // 解析未发生错误
        if (document.isObject()) { // JSON 文档为对象
            QJsonObject rootObject = document.object();  // 转化为对象
            if (rootObject.contains("Version")) {  // 包含指定的 key
                QJsonValue value = rootObject.value("Version");  // 获取指定 key 对应的 value
                if (value.isString()) {  // 判断 value 是否为字符串
                    //QString strName = value.toString();  // 将 value 转化为字符串
                    qDebug() << "[Updater]Version : " << value.toString();
                }
                if (value.isDouble()) {  // 判断 value 是否为
                    qDebug() << "[Updater]Version : " << value.toDouble();
                }
            }
            if (rootObject.contains("FileList")) {
                QJsonValue value = rootObject.value("FileList");
                if (value.isArray()) {  // Version 的 value 是数组
                    QJsonArray filelist = value.toArray();
                    int nSize = filelist.size();
                    for (int i = 0; i < nSize; ++i) {
                        QJsonValue value = filelist.at(i);
                        if (value.isObject()) {
                            QJsonObject joFileInfo = value.toObject();
                            if (joFileInfo.contains("FilePath")) {
                                QString strPath = joFileInfo.value("FilePath").toString();  // 将 value 转化为字符串
                                qDebug() << "[Updater]FilePath : " << strPath;
                            }
                            if (joFileInfo.contains("Version")) {
                                int fileVersion = joFileInfo.value("Version").toInt();  // 将 value 转化为字符串
                                qDebug() << "[Updater]Version : " << fileVersion;
                            }
                        }
                    }
                }
            }
        }
    }
    else
        return false;

    return true;
}

